package com.dianxun.bookmanager.utils;

import android.annotation.SuppressLint;
import android.nfc.NdefRecord;
import android.nfc.tech.NfcV;

import java.io.IOException;
import java.util.Arrays;


/**
 * @author cloin 用法 NfcV mNfcV = NfcV.get(tag); mNfcV.connect(); NfcVUtil
 * mNfcVutil = new NfcVUtil(mNfcV); 取得UID mNfcVutil.getUID();
 * 读取block在1位置的内容 mNfcVutil.readOneBlock(1);
 * 从位置7开始读2个block的内容
 * mNfcVutil.readBlocks(7, 2);
 * 取得block的个数 mNfcVutil.getBlockNumber();
 * 取得1个block的长度 mNfcVutil.getOneBlockSize(); 往位置1的block写内容
 * mNfcVutil.writeBlock(1, new byte[]{0, 0, 0, 0})
 */
@SuppressLint("NewApi")
public class ISO15693 {
    private NfcV mNfcV;
    /**
     * UID数组行式
     */
    private byte[] ID;
    private String UID;
    private String DSFID;
    private String AFI;
    /**
     * block的个数
     */
    private int blockNumber;
    /**
     * 一个block长度
     */
    private int oneBlockSize;
    /**
     * 信息
     */
    private byte[] infoRmation;


    /**
     * 初始化
     *
     * @param mNfcV NfcV对象
     * @throws IOException
     */
    @SuppressLint("NewApi")
    public ISO15693(NfcV mNfcV) throws IOException {
        this.mNfcV = mNfcV;
        ID = this.mNfcV.getTag().getId();
        byte[] uid = new byte[ID.length];
        int j = 0;
        for (int i = ID.length - 1; i >= 0; i--) {
            uid[j] = ID[i];
            j++;
        }
        this.UID = printHexString(uid);
        getInfoRmation();
    }


    public String getUID() {
        return UID;
    }


    /**
     * 取得标签信息
     */
    private byte[] getInfoRmation() throws IOException {
        byte[] cmd = new byte[10];
        cmd[0] = (byte) 0x22; // flag
        cmd[1] = (byte) 0x2B; // command
        System.arraycopy(ID, 0, cmd, 2, ID.length); // UID
        infoRmation = mNfcV.transceive(cmd);
        blockNumber = infoRmation[12];
        oneBlockSize = infoRmation[13];
        AFI = printHexString(new byte[]{infoRmation[11]});
        DSFID = printHexString(new byte[]{infoRmation[10]});
        return infoRmation;
    }


    public String getDSFID() {
        return DSFID;
    }


    public String getAFI() {
        return AFI;
    }


    public int getBlockNumber() {
        return blockNumber + 1;
    }


    public int getOneBlockSize() {
        return oneBlockSize + 1;
    }


    /**
     * 读取一个位置在position的block
     *
     * @param position 要读取的block位置
     * @return 返回内容字符串
     * @throws IOException
     */
    public String readOneBlock(int position) throws IOException {
        byte cmd[] = new byte[11];
        cmd[0] = (byte) 0x22;
        cmd[1] = (byte) 0x20;
        System.arraycopy(ID, 0, cmd, 2, ID.length); // UID
        cmd[10] = (byte) position;
        byte res[] = mNfcV.transceive(cmd);
        if (res[0] == 0x00) {
            byte block[] = new byte[res.length - 1];
            System.arraycopy(res, 1, block, 0, res.length - 1);
            return printHexString(block);
        }
        return null;
    }

    /**
     * 读取一个位置在position的block
     *
     * @return 返回内容字符串
     * @throws IOException
     */
    public String readBookInfo() throws IOException {
        byte[] result = new byte[7];
        byte cmd[] = new byte[11];
        cmd[0] = (byte) 0x22;
        cmd[1] = (byte) 0x20;
        System.arraycopy(ID, 0, cmd, 2, ID.length); // UID
        cmd[10] = (byte) 0;
        byte res[] = mNfcV.transceive(cmd);
        if (res[0] == 0x00) {
            System.arraycopy(res, 1, result, 0, res.length - 1);
//            return printHexString(block);
        }
        cmd[10] = (byte) 1;
        res = mNfcV.transceive(cmd);
        if (res[0] == 0x00) {
            System.arraycopy(res, 1, result, 4, 3);
//            return printHexString(block);
        }
        return new String(result);
    }


    /**
     * 读取从begin开始end个block begin + count 不能超过blockNumber
     *
     * @param begin block开始位置
     * @param count 读取block数量
     * @return 返回内容字符串
     * @throws IOException
     */
    public String readBlocks(int begin, int count) throws IOException {
        if ((begin + count) > blockNumber) {
            count = blockNumber - begin;
        }
        StringBuffer data = new StringBuffer();
        for (int i = begin; i < count + begin; i++) {
            data.append(readOneBlock(i));
        }
        return data.toString();
    }


    /**
     * 将byte[]转换成16进制字符串
     *
     * @param data 要转换成字符串的字节数组
     * @return 16进制字符串
     */
    private String printHexString(byte[] data) {
        StringBuffer s = new StringBuffer();
        for (int i = 0; i < data.length; i++) {
            String hex = Integer.toHexString(data[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            s.append(hex);
        }
        return s.toString();
    }


    /**
     * 将数据写入到block,
     *
     * @param position 要写内容的block位置
     * @param data     要写的内容,必须长度为blockOneSize
     * @return false为写入失败，true为写入成功
     * @throws IOException
     */
    public boolean writeBlock(int position, byte[] data) throws IOException {
        byte cmd[] = new byte[15];
        cmd[0] = (byte) 0x22;
        cmd[1] = (byte) 0x21;
        System.arraycopy(ID, 0, cmd, 2, ID.length); // UID
// block
        cmd[10] = (byte) position;
// value
        System.arraycopy(data, 0, cmd, 11, data.length);
        byte[] rsp = mNfcV.transceive(cmd);
        if (rsp[0] == 0x00)
            return true;
        return false;
    }


    public static String parseTextRecord(NdefRecord ndefRecord) {
        /**
         * 判断数据是否为NDEF格式
         */
        //判断TNF
        if (ndefRecord.getTnf() != NdefRecord.TNF_WELL_KNOWN) {
            return null;
        }
        //判断可变的长度的类型
        if (!Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_TEXT)) {
            return null;
        }
        try {
            //获得字节数组，然后进行分析
            byte[] payload = ndefRecord.getPayload();
            //下面开始NDEF文本数据第一个字节，状态字节
            //判断文本是基于UTF-8还是UTF-16的，取第一个字节"位与"上16进制的80，16进制的80也就是最高位是1，
            //其他位都是0，所以进行"位与"运算后就会保留最高位
            String textEncoding = ((payload[0] & 0x80) == 0) ? "UTF-8" : "UTF-16";
            //3f最高两位是0，第六位是1，所以进行"位与"运算后获得第六位
            int languageCodeLength = payload[0] & 0x3f;
            //下面开始NDEF文本数据第二个字节，语言编码
            //获得语言编码
            String languageCode = new String(payload, 1, languageCodeLength, "US-ASCII");
            //下面开始NDEF文本数据后面的字节，解析出文本
            String textRecord = new String(payload, languageCodeLength + 1,
                    payload.length - languageCodeLength - 1, textEncoding);
            return textRecord;
        } catch (Exception e) {
            throw new IllegalArgumentException();
        }
    }
}